
#include    "File/MapLoader.hpp"

using namespace File;

MapLoader::MapLoader() : _map(0)
{

}

MapLoader::~MapLoader()
{
    if (this->_map != 0)
    {
        delete this->_map;
        this->_map = 0;
    }
}

Scene::Game::Map*    MapLoader::loadFile(std::string const & filename)
{
    try
    {
        this->_xmlFile.LoadFile(filename);
        ticpp::Element* root = this->_xmlFile.FirstChildElement();
        this->_initSize(root->FirstChildElement("size"));
        this->_initTextures(root->FirstChildElement("textures"));
        this->_initItems(root->FirstChildElement("items"));
        this->_initPositions(root->FirstChildElement("positions"));
    } catch (ticpp::Exception& e) {
        std::cout << "Could not open map file " << filename << ":" << std::endl << e.what() << std::endl;
    }
    return this->_map;
}

void    MapLoader::_initSize(ticpp::Element* sizeTag)
{
    try
    {
        int width, height;

        sizeTag->GetAttribute("width", &width);
        sizeTag->GetAttribute("height", &height);
        if (width > 0 && height > 0)
        {
            this->_map = new Scene::Game::Map(width, height);
            std::cout << "Map initialized with a size of " << width << "/" << height << std::endl;
        }
    } catch (ticpp::Exception& e) {
        std::cout << "Map size tag misformed: " << std::endl << e.what() << std::endl;
    }
}

void    MapLoader::_initTextures(ticpp::Element* texturesTag)
{
    try
    {
        int id;
        std::string file;

        ticpp::Iterator<ticpp::Element> it("texture");
        for (it = it.begin(texturesTag); it != it.end(); it++)
        {
            it->GetAttribute("id", &id);
            it->GetAttribute("file", &file);
            std::cout << "texture id: " << id << "\tfile: " << file << std::endl;
        }
    } catch (ticpp::Exception& e) {
        std::cout << "Textures are not defined well: " << std::endl << e.what() << std::endl;
    }
}

void    MapLoader::_initItems(ticpp::Element* itemsTag)
{
    try
    {
        ticpp::Iterator<ticpp::Element> it("item");
        for (it = it.begin(itemsTag); it != it.end(); it++)
            this->_initItem(*it);
    } catch (ticpp::Exception& e) {
        std::cout << "Loading items failed: " << std::endl << e.what() << std::endl;
    }
}

void    MapLoader::_initItem(ticpp::Element const & itemTag)
{
    try
    {
        int         x, y, z, textureId, density;
        bool        traversable;
        std::string name;

        ticpp::Element* sizeEl = itemTag.FirstChildElement("size");
        ticpp::Element* textureEl = itemTag.FirstChildElement("texture");
        ticpp::Element* densityEl = itemTag.FirstChildElement("density", false);
        ticpp::Element* traversableEl = itemTag.FirstChildElement("traversable", false);
        itemTag.GetAttribute("name", &name);
        sizeEl->GetAttribute("x", &x);
        sizeEl->GetAttribute("y", &y);
        sizeEl->GetAttributeOrDefault("z", &z, 0);
        textureEl->GetAttribute("id", &textureId);
        if (densityEl)
            densityEl->GetAttributeOrDefault("value", &density, 80);
        else
            density = 80;
        if (traversableEl)
            traversableEl->GetAttributeOrDefault("traversable", &traversable, false);
        else
            traversable = false;
        std::cout << "Creating Item <" << name << ">:" << std::endl
            << "dimensions: x=" << x << "\ty=" << y << "\tz=" << z << std::endl
            << "texture: " << textureId << "\tdensity: " << density << "\ttraversable:" << traversable << std::endl;
        this->_map->addItem(name, new MapItem(x, y, z, textureId, density, traversable));
    } catch (ticpp::Exception& e) {
        std::cout << "Loading item failed: " << std::endl << e.what() << std::endl;
    }
}

void    MapLoader::_initPositions(ticpp::Element* positionsTag)
{
    try
    {
        int         x, y;
        std::string itemName;

        ticpp::Iterator<ticpp::Element> it("position");
        for (it = it.begin(positionsTag); it != it.end(); it++)
        {
            it->GetAttribute("x", &x);
            it->GetAttribute("y", &y);
            it->GetAttribute("itemname", &itemName);
            std::cout << "Need to place item <" << itemName << "> at x=" << x << " y=" << y << std::endl;
        }
    } catch (ticpp::Exception& e) {
        std::cout << "Position of item cannot be retrieved: " << std::endl << e.what() << std::endl;
    }
}
